package cn.dyw.engine.core.limit;

import cn.dyw.engine.core.context.ReportStandardContext;
import cn.dyw.engine.core.exec.DbTypeHolder;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLLimit;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import lombok.extern.slf4j.Slf4j;

/**
 * mysql limit
 *
 * @author dyw770
 * @since 2021-08-10
 */
@Slf4j
public class DefaultLimitRender implements ILimitRender {

    @Override
    public String limitRender(String sql, ReportStandardContext context) {
        ExecLimit execLimit = context.getLimit();
        DbType dbType = DbTypeHolder.get();
        SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils.parseSingleStatement(sql, context.getDbType());
        SQLSelectQuery query = stmt.getSelect().getQuery();
        // 先不考虑 union 的 SQL
        if (query instanceof SQLSelectQueryBlock) {
            SQLSelectQueryBlock sqb = (SQLSelectQueryBlock) query;

            SQLLimit limit = sqb.getLimit();
            if (limit == null && execLimit != null) {

                SQLLimit sqlLimit = new SQLLimit();
                sqlLimit.setOffset(buildOffset(execLimit));
                sqlLimit.setRowCount(execLimit.getLimit());

                sqb.setLimit(sqlLimit);
                String limitSql = SQLUtils.toSQLString(sqb, dbType);
                log.debug("渲染 limit sql: {}", limitSql);
                return limitSql;
            }
        }
        return sql;
    }

    private int buildOffset(ExecLimit execLimit) {
        if (execLimit.getPage() > 0) {
            return execLimit.getLimit() * (execLimit.getPage() - 1);
        }
        return 0;
    }
}
